import LazyImage from '@/component/LazyImage'
import { useI18n } from '@/i18n'
import { processGIF } from '@/lib/gif'
import ClearSvg from '@/svg/ClearSvg'
import DeleteSvg from '@/svg/DeleteSvg'
import DelWatermarkSvg from '@/svg/DelWatermarkSvg'
import ExportSvg from '@/svg/ExportSvg'
import GeSelecgSvg from '@/svg/GeSelecgSvg'
import GifSvg from '@/svg/GifSvg'
import ImageSvg from '@/svg/ImageSvg'
import ImgClipSvg from '@/svg/ImgClipSvg'
import ImportSvg from '@/svg/ImportSvg'
import MoreImageSvg from '@/svg/MoreImageSvg'
import MoreSvg from '@/svg/MoreSvg'
import RemoveBgSvg from '@/svg/RemoveBgSvg'
import ResizeSvg from '@/svg/ResizeSvg'
import SelectAllSvg from '@/svg/SelectAllSvg'
import SettingSvg from '@/svg/SettingSvg'
import VideoSvg from '@/svg/VideoSvg'
import { sleep } from '@/utils/common'
import { showContextMenu } from '@/utils/contextMenu'
import { showLoading } from '@/utils/loading'
import { MessageBox } from '@/utils/messageBox'
import { showToast } from '@/utils/toast'
import { invoke } from '@tauri-apps/api/core'
import { readDir, readFile } from '@tauri-apps/plugin-fs'
import { useRef, useState } from 'react'
import { ReactSortable } from 'react-sortablejs'
interface Props {
  setLastHoverIndex: (index: number) => void
  onResizeImage: () => void
  onRemoveBg: () => void
  onOpenSetting: () => void
  onGeSelect: () => void
  onClipImage: () => void
  onDelWatermark: () => void
  imageList: FrameInfo[]
  frameList: FrameInfo[]
  setImageList: React.Dispatch<React.SetStateAction<FrameInfo[]>>
  selectList: string[]
  setSelectList: React.Dispatch<React.SetStateAction<string[]>>

  // 导出
  onExportSpriteSheet: () => void
  onExportImageList: () => void
  onExportVideo: () => void
}
const allowImageTypes = ['image/jpeg', 'image/png', 'image/bmp', 'image/webp']
const ImageFrameList = (props: Props) => {
  const { imageList, setImageList, selectList, setSelectList } = props
  const [lastHoverIndex, setLastHoverIndex] = useState<number>(-1)
  const isEmpty = imageList.length === 0
  const imageInputRef = useRef<HTMLInputElement>(null)
  const imageGifInputRef = useRef<HTMLInputElement>(null)
  const imageVideoInputRef = useRef<HTMLInputElement>(null)
  function uploadImages(files: File[]) {
    const notAllowImages: string[] = []
    const newImageList: File[] = []
    // 文件校验
    for (let file of files) {
      if (!allowImageTypes.includes(file.type)) {
        notAllowImages.push(file.name)
        continue
      }
      newImageList.push(file)
    }
    if (newImageList.length > 0) {
      const value = newImageList.map((item) => {
        return {
          file: item,
          name: item.name,
          url: URL.createObjectURL(item),
        }
      })
      setImageList((prev) => [...prev, ...value])
      setSelectList((prev) => {
        return [...prev, ...value.map((item) => item.url)]
      })
    }
    if (notAllowImages.length > 0) {
      MessageBox.warn(
        '文件格式错误',
        `文件 ${notAllowImages.join(',')} 格式不正确`
      )
    }
  }

  async function uploadGifImage(file: File) {
    if (!file) return
    if (file.type != 'image/gif') {
      showToast('错误的文件格式')
      return
    }
    const hideloading = showLoading('文件解析中')
    try {
      const res = await processGIF(file)
      const list = res.frames.map((item) => {
        return {
          file: item,
          name: item.name,
          url: URL.createObjectURL(item),
        }
      })
      if (list.length > 0) {
        setImageList((prev) => [...prev, ...list])
        setSelectList((prev) => {
          return [...prev, ...list.map((item) => item.url)]
        })
      }
    } catch (e) {
      console.error(e)
      showToast('文件解析失败')
    } finally {
      hideloading()
    }
  }
  async function uploadVideo(file: File) {
    if (!file) return
    if (file.type.indexOf('video/') !== 0) {
      showToast('错误的文件格式')
      return
    }

    const hideloading = showLoading('文件解析中')
    try {
      const buffer = await file.arrayBuffer()
      const res: string = await invoke('mp4_to_png', {
        buffer,
      })
      const list = await readDir(res)
      const newImageList: FrameInfo[] = []
      for (let item of list) {
        const arrayBuffer = await readFile(`${res}/${item.name}`)
        const blob = new Blob([arrayBuffer], { type: 'image/png' })
        const file = new File([blob], item.name, { type: 'image/png' })
        const url = URL.createObjectURL(blob)
        newImageList.push({
          file,
          url,
          name: item.name,
        })
      }
      if (newImageList.length > 0) {
        setImageList((prev) => [...prev, ...newImageList])
        setSelectList((prev) => {
          return [...prev, ...newImageList.map((item) => item.url)]
        })
      }
    } catch (e) {
      console.error(e)
      showToast('文件解析失败:' + e)
    } finally {
      hideloading()
    }
  }
  const [imageWidth, _] = useState(100)
  const isSelectAll = imageList.every((item) => selectList.includes(item.url))

  const { t } = useI18n()
  return (
    <div className="ImageFrameList">
      <div
        className="top-tool-btn-list"
        onWheel={(e) => {
          // e.deltaY
          e.currentTarget.scroll({
            left: e.currentTarget.scrollLeft + e.deltaY / 2,
          })
        }}>
        <div className="top-tool-btn-list-inner">
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={(e) => {
              const rect = e.currentTarget.getBoundingClientRect()
              showContextMenu(
                [
                  {
                    key: 'images',
                    label: t('importImageFrames'),
                  },
                  {
                    key: 'video',
                    label: t('importVideo'),
                    // label: '导入MP4',
                  },
                  {
                    key: 'gif',
                    label: t('importGif'),
                  },
                ],
                (e) => {
                  switch (e) {
                    case 'images':
                      imageInputRef.current.click()
                      break
                    case 'video':
                      imageVideoInputRef.current.click()
                      break
                    case 'gif':
                      imageGifInputRef.current.click()
                  }
                },
                {
                  x: rect.left,
                  y: rect.bottom - 5,
                }
              )
            }}>
            <ImportSvg className="icon" />
            <span>{t('import')}</span>
          </ripple-button>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={(e) => {
              const rect = e.currentTarget.getBoundingClientRect()
              showContextMenu(
                [
                  {
                    key: 'sprite',
                    label: t('exportSprite'),
                  },
                  {
                    key: 'image',
                    label: t('exportImageCollection'),
                  },
                  {
                    key: 'video',
                    label: t('exportVideo'),
                  },
                ],
                (e) => {
                  if (!props.frameList.length) {
                    showToast(t('pleaseAddFramesFirst'))
                    return
                  }
                  switch (e) {
                    case 'sprite':
                      props.onExportSpriteSheet()
                      break
                    case 'image':
                      props.onExportImageList()
                      break
                    case 'video':
                      props.onExportVideo()
                  }
                },
                {
                  x: rect.left,
                  y: rect.bottom - 5,
                }
              )
            }}>
            <ExportSvg className="icon" />
            <span>{t('export')}</span>
          </ripple-button>
          <div style={{ width: 15 }}></div>

          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={props.onResizeImage}>
            <ResizeSvg className="icon" />
            <span>{t('resize')}</span>
          </ripple-button>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={props.onRemoveBg}>
            <RemoveBgSvg className="icon" />
            <span>{t('removeBackground')}</span>
          </ripple-button>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={props.onClipImage}>
            <ImgClipSvg className="icon" />
            <span>{t('canvasCutting')}</span>
          </ripple-button>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={props.onDelWatermark}>
            <DelWatermarkSvg className="icon" />
            <span>{t('regionalCoverage')}</span>
          </ripple-button>
          <div style={{ width: 15 }}></div>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={() => {
              if (isSelectAll) {
                setSelectList([])
              } else {
                setSelectList(imageList.map((item) => item.url))
              }
            }}>
            <SelectAllSvg className="icon" />
            <span>{isSelectAll ? t('deselectAll') : t('selectAll')}</span>
          </ripple-button>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={() => {
              setImageList([])
              setSelectList([])
            }}>
            <ClearSvg className="icon" />
            <span>{t('clear')}</span>
          </ripple-button>
          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={(e) => {
              const rect = e.currentTarget.getBoundingClientRect()
              showContextMenu(
                [
                  {
                    key: 'geSelect',
                    label: t('separateSelection'),
                  },
                  {
                    key: 'invertSelection',
                    label: t('invertSelection'),
                  },
                  {
                    key: 'deleteUnSelected',
                    label: t('deleteUnselectedItems'),
                  },
                ],
                (e) => {
                  switch (e) {
                    case 'geSelect':
                      props.onGeSelect()
                      break
                    case 'deleteUnSelected':
                      setImageList((pre) => {
                        return pre.filter((item) => {
                          return selectList.includes(item.url)
                        })
                      })
                      showToast(t('deletedSuccessfully'))
                      break
                    case 'invertSelection':
                      setSelectList((pre) => {
                        return imageList
                          .map((item) => item.url)
                          .filter((item) => !pre.includes(item))
                      })
                  }
                },
                {
                  x: rect.left,
                  y: rect.bottom - 5,
                }
              )
            }}>
            <MoreSvg className="icon" />
            <span>{t('more')}</span>
          </ripple-button>
          <div style={{ width: 15 }}></div>

          <ripple-button
            className="item"
            ripple-color="#b081f577"
            onClick={() => {
              props.onOpenSetting()
            }}>
            <SettingSvg className="icon" />
            <span>{t('setting')}</span>
          </ripple-button>
        </div>
      </div>
      <div
        tabIndex={-1}
        className="cont-view"
        onDrop={(e) => {
          e.preventDefault()
          e.stopPropagation()
          const files = e.dataTransfer.files
          if (files.length == 0) return
          const file = files[0]
          if (file.type.indexOf('video/') === 0) {
            uploadVideo(file)
          } else if (file.type == 'image/gif') {
            uploadGifImage(file)
          } else if (allowImageTypes.includes(file.type)) {
            uploadImages(Array.from(files))
          } else showToast(t('wrongFileFormat'))
        }}
        onDragOver={(e) => {
          const allowImages = [
            ...allowImageTypes,
            'image/gif',
            'video/mp4',
            'video/webm',
            'video/mpg',
          ]
          const file = e.dataTransfer.items
          for (let i = 0; i < file.length; i++) {
            if (!allowImages.includes(file[i].type)) {
              continue
            }
            e.preventDefault()
            return
          }
        }}
        onKeyDown={(e) => {
          if (
            e.key == 'Delete' &&
            imageList.length > lastHoverIndex &&
            lastHoverIndex >= 0
          ) {
            setImageList((pre) => {
              return pre.filter((item, index) => {
                if (index != lastHoverIndex) {
                  return true
                }
                sleep(100).then(() => URL.revokeObjectURL(item.url))
                return false
              })
            })
          }
        }}>
        {isEmpty ? (
          <div className="empty">
            <ImageSvg fill="#888" className="icon" />
            <span>{t('dragTheMaterialToTheDesignatedArea')}</span>
          </div>
        ) : (
          <ReactSortable
            dataIdAttr="url"
            // @ts-ignore
            list={imageList}
            className="image-list"
            style={{
              // @ts-ignore
              '--image-width': `${imageWidth}px`,
            }}
            setList={(list: any[]) => {
              // console.log(list)
              setImageList(list)
            }}>
            {imageList.map((item, index) => {
              return (
                <div
                  onMouseEnter={() => {
                    setLastHoverIndex(index)
                    if (selectList.includes(item.url)) {
                      props.setLastHoverIndex(
                        imageList
                          .filter((item) => selectList.includes(item.url))
                          .findIndex((item2) => {
                            return item2.url == item.url
                          })
                      )
                    }
                  }}
                  onClick={() => {
                    setSelectList((pre) => {
                      if (pre.includes(item.url)) {
                        return pre.filter((i) => i != item.url)
                      }
                      return [...pre, item.url]
                    })
                  }}
                  className={
                    'image-item ' +
                    (selectList.includes(item.url) ? 'select' : '')
                  }
                  key={item.url}>
                  {/* <img
                    draggable={false}
                    src={item.url}
                    className="img"
                    loading="lazy"
                    alt=""
                  /> */}
                  <LazyImage
                    draggable={false}
                    src={item.url}
                    className="img"
                    alt=""
                  />
                  <span>{item.file.name}</span>
                </div>
              )
            })}
          </ReactSortable>
        )}
      </div>
      <input
        ref={imageInputRef}
        type="file"
        multiple
        accept={allowImageTypes.join(',')}
        style={{ display: 'none' }}
        onChange={(e) => {
          const files = e.target.files
          if (files.length == 0) return
          if (files) {
            uploadImages(Array.from(files))
          }
          e.target.value = ''
        }}
      />
      <input
        ref={imageGifInputRef}
        type="file"
        accept="image/gif"
        style={{ display: 'none' }}
        onChange={(e) => {
          const files = e.target.files
          if (files.length == 0) return
          if (files) {
            uploadGifImage(files[0])
          }
          e.target.value = ''
        }}
      />
      <input
        ref={imageVideoInputRef}
        type="file"
        accept="video/*"
        style={{ display: 'none' }}
        onChange={(e) => {
          const files = e.target.files
          if (files.length == 0) return
          if (files) {
            uploadVideo(files[0])
          }
          e.target.value = ''
        }}
      />
    </div>
  )
}

export default ImageFrameList
